﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.UnitTests.TestClasses.ValidationObjects.Automobile;
using StyleMVVM.Validation;
using StyleMVVM.Validation.Impl;
using StyleMVVM.Validation.Impl.Fluent;
#if NETFX_CORE
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Windows.ApplicationModel.Resources;

#else
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endif

namespace StyleMVVM.UnitTests.Validation.Fluent
{
	[TestClass]
	public class DoublePropertyModifierTests : BaseTestClass
	{
		[TestMethod]
		public void PlusOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Plus(4).GreaterThan.Value(4.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car();

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 1;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void SubtractOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Minus(4).GreaterThan.Value(4.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 8 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 9;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void MultiplyOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Multiply(4).GreaterThan.Value(16.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 0 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 5;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void DivideOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Divide(4).GreaterThan.Value(4.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 16 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 20;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void ModOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Mod(4).GreaterThan.Value(2.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 0 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 11;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void FloorOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Floor().GreaterThan.Value(2.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 2.5 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 3.0;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void CeilingOperatorRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WeightRule");

			wheelsRule.DoubleProperty(x => x.Weight).Ceiling().GreaterThan.Value(2.0);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Weight = 2.0 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Weight = 2.1;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}
	}
}